package com.comment.utils;

import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class SimpleRedisLock implements ILock {

    /**
     * 锁的Key名称
     */
    private String name;
    /**
     * RedisTemplate
     */
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 锁的key名称前缀
     */
    private static final String KEY_PREFIX = "lock:";

    /**
     * 线程ID前缀
     */
    private static final String THREAD_PREFIX = UUID.randomUUID().toString() + "-";

    /**
     * 构造函数（保证name和stringRedisTemplate传入）
     *
     * @param name                传入的锁的key名称
     * @param stringRedisTemplate 传入的RedisTemplate
     */
    public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
        this.name = name;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 尝试获取锁
     *
     * @param timeoutSec 锁的过期时间
     * @return true/false true表示获取锁成功，false表示获取锁失败
     */
    @Override
    public boolean tryLock(long timeoutSec) {
        // 2.获取线程id
        String threadId = THREAD_PREFIX + Thread.currentThread().getId();
        // 1.尝试获取锁
        Boolean flag = stringRedisTemplate.opsForValue()
                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        // 3.防止拆箱，出现空指针异常，判断返回
        return Boolean.TRUE.equals(flag);
    }

    /**
     * 释放锁
     */
    @Override
    public void unLock() {
        // 1.获取线程标识
        String threadId = THREAD_PREFIX + Thread.currentThread().getId();
        // 2.获取锁中标识
        String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
        // 3.判断锁标识是否一致
        if (threadId.equals(id)) {
            // 4.一致，释放锁
            stringRedisTemplate.delete(KEY_PREFIX + name);
        }
    }
}
